/*
    实现环形队列和阻塞队列
*/

#ifndef __M_QUEUE_H__
#define __M_QUEUE_H__

#include <iostream>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <chrono>

namespace maglog {

    // 环形队列类，支持基本的队列操作
    template <typename T>
    class RingQueue {
        private:
            size_t _capacity;       // 队列的最大容量
            size_t _read_pos;       // 读取位置索引
            size_t _write_pos;      // 写入位置索引
            std::vector<T> _v;      // 存储队列元素的容器

        public:
            // 显式构造函数，防止隐式类型转换
            explicit RingQueue(size_t capacity)
                : _capacity(capacity), _read_pos(0), _write_pos(0), _v(capacity) {}

            // 将元素推入队列
            void push(const T &&item) {
                if (full()) {
                    std::cerr << "队列已满，无法推入元素" << std::endl;
                    return;
                }
                _v[_write_pos] = std::move(item);
                _write_pos = (_write_pos + 1) % _capacity;
            }

            // 获取队列中的第一个元素（不可修改）
            const T& front() {
                if (empty()) {
                    throw std::out_of_range("队列为空");
                }
                return _v[_read_pos];
            }

            // 获取队列中的第一个元素（可修改）
            T& front() {
                if (empty()) {
                    throw std::out_of_range("队列为空");
                }
                return _v[_read_pos];
            }

            // 从队列中移除第一个元素
            void pop() {
                if (empty()) {
                    std::cerr << "队列为空，无法移除元素" << std::endl;
                    return;
                }
                _read_pos = (_read_pos + 1) % _capacity;
            }

            // 检查队列是否为空
            bool empty() {
                return _read_pos == _write_pos;
            }

            // 检查队列是否已满
            bool full() {
                return (_write_pos + 1) % _capacity == _read_pos;
            }
    };

    // 阻塞队列类，基于环形队列实现，支持线程安全的队列操作
    template<typename T>
    class BlockQueue {
        private:
            RingQueue<T> _q;                  // 环形队列实例
            std::mutex _mutex;                // 互斥锁，保证线程安全
            std::condition_variable _cond_push; // 用于通知可以推入元素
            std::condition_variable _cond_pop;  // 用于通知可以移除元素

        public:
            // 构造函数，初始化阻塞队列
            BlockQueue(size_t capacity) : _q(capacity) {}

            // 将元素推入阻塞队列
            void enqueue(T &&item) {
                std::unique_lock<std::mutex> lock(_mutex);
                _cond_push.wait(lock, [this] { return !_q.full(); });
                _q.push(std::move(item));
                _cond_pop.notify_one();
            }

            // 从阻塞队列中移除元素并返回
            T& dequeue(std::chrono::milliseconds duration = std::chrono::milliseconds(-1)) {
                std::unique_lock<std::mutex> lock(_mutex);
                if (duration.count() == -1) {
                    _cond_pop.wait(lock, [this] { return !_q.empty(); });
                } else {
                    if (!_cond_pop.wait_for(lock, duration, [this] { return !_q.empty(); })) {
                        throw std::runtime_error("超时");
                    }
                }
                T& item = _q.front();
                _q.pop();
                _cond_push.notify_one();
                return item;
            }

            // 获取阻塞队列中的元素数量
            size_t size() {
                std::unique_lock<std::mutex> lock(_mutex);
                return _q.size();
            }
    };

} // namespace maglog

#endif // __M_QUEUE_H__
